﻿namespace MaterialSkin.Controls
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;



    public class MaterialGroupBox : Control, IMaterialControl
    {
        //Properties for managing the material design properties
        [Browsable(false)]
        public int Depth { get; set; }

        [Browsable(false)]
        public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;

        [Browsable(false)]
        public MouseState MouseState { get; set; }

        //internal AnimationManager AnimationManager;

        private const int MIN_WIDTH = 20;
        private const int MIN_HEIGHT = 10;

        private const float TEXT_START_X = 8;
        private const float TEXT_START_Y = 2;
        private const float TOP_FIRST_LINE_END_X = TEXT_START_X;

        
        private const float SHADOW_LINE_BIAS = 1;
        //include one line and one shadow line,so bias is 2
        private const float LINE_BIAS = 2 * SHADOW_LINE_BIAS;

        private SizeF textSize = default;
        private Rectangle textRect = new Rectangle();




        private Color _BackColor = SystemColors.ControlText;

        [Browsable(false)]
        public override Color BackColor
        {
            get
            {
                return _BackColor;
            }
            set
            {
                if (Parent != null)
                    _BackColor = Parent.BackColor;
                else
                    _BackColor = SkinManager.BackdropColor;
                Invalidate();
            }

        }
        
        //ENUM
        private GroupBoxFontType _FontType = GroupBoxFontType.Subtitle2;
        [Category("Material")]
        public GroupBoxFontType FontType
        {
            get
            {
                return _FontType;
            }
            set
            {
                _FontType = value;
                computeTextSize(_Text);
                Invalidate();
            }
        }
        //not use
        private Font _Font = SystemFonts.DefaultFont;
        [Browsable(false)]
        public override Font Font 
        {
            get
            {
                return _Font;
            }
            set
            {
                _Font = SkinManager.getFontByType((MaterialSkinManager.fontType)_FontType);
                Invalidate();
            }
        }
        //
        private Color _ForeColor = SystemColors.Control;
        [Browsable(false)]
        public override Color ForeColor
        {
            get 
            {
                return _ForeColor; 
            }
            set
            {
                _ForeColor = SkinManager.TextHighEmphasisColor;
                Invalidate();
            }
        }
        //

        private string _Text = string.Empty;
        [Category("Material"), Localizable(true)]
        public override string Text
        {
            get { return _Text; }
            set
            {
                _Text = value.Trim();
                computeTextSize(_Text);
                allocateSize();
                Invalidate();
            }
        }

        public MaterialGroupBox()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | 
                ControlStyles.DoubleBuffer | ControlStyles.ResizeRedraw, true);
            //init the backcolor
            if (Parent != null)
                _BackColor = Parent.BackColor;
            else
                _BackColor = SkinManager.BackdropColor;

            _FontType = GroupBoxFontType.Subtitle2;
            //not use
            _Font = SkinManager.getFontByType((MaterialSkinManager.fontType)_FontType);

            _ForeColor = SkinManager.TextHighEmphasisColor;
            _Text = this.Name;
            computeTextSize(_Text);
            //if true, the text is clear
            //DoubleBuffered = true;

        }

        private void allocateSize()
        {
            float minWidth = TOP_FIRST_LINE_END_X + this.textSize.Width;

            if (this.Width < minWidth) this.Width = (int)Math.Ceiling(minWidth);

            if (this.Height < this.textSize.Height) this.Height = (int)Math.Ceiling(this.textSize.Height);

            if (this.Width < MIN_WIDTH) this.Width = MIN_WIDTH;

            if (this.Height < MIN_HEIGHT) this.Height = MIN_HEIGHT;


        }


        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);

            allocateSize();

            Invalidate();
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.Clear(Parent.BackColor);


            //if (!string.IsNullOrWhiteSpace(this.Text))
            //    g.DrawString(this.Text, SkinManager.getFontByType(MaterialSkinManager.fontType.Subtitle2), SkinManager.TextHighEmphasisBrush, TEXT_START_X, TEXT_START_Y);
            //Draw title
            textRect.Size = this.textSize.ToSize();
            textRect.Location = new Point((int)TEXT_START_X, (int)TEXT_START_Y);

            using (NativeTextRenderer NativeText = new NativeTextRenderer(g))
            {
                // Draw header text
                NativeText.DrawTransparentText(
                    this.Text,
                    SkinManager.getLogFontByType((MaterialSkinManager.fontType)_FontType),
                    _ForeColor,//SkinManager.TextHighEmphasisColor,
                    textRect.Location,
                    textRect.Size,
                    NativeTextRenderer.TextAlignFlags.Center | NativeTextRenderer.TextAlignFlags.Middle);
            }


            this.textSize.Height = this.textSize.Height == 0 ? TEXT_START_Y : this.textSize.Height;

            float startEndY = (float)Math.Ceiling(this.textSize.Height / 2) + SHADOW_LINE_BIAS;
            //line width = 1
            using (Pen linePen = new Pen(SkinManager.GroupBoxLineColor, 1),
                lineShadowPen = new Pen(Color.FromArgb(12, 0, 0, 0), 1))
            {
                //top first line
                g.DrawLine(linePen, 1, startEndY, TOP_FIRST_LINE_END_X, startEndY);
                g.DrawLine(lineShadowPen, 1, startEndY - SHADOW_LINE_BIAS, TOP_FIRST_LINE_END_X, startEndY - SHADOW_LINE_BIAS);

                //top second line
                g.DrawLine(linePen, this.textSize.Width + TOP_FIRST_LINE_END_X, startEndY, this.Width - LINE_BIAS, startEndY);
                g.DrawLine(lineShadowPen, this.textSize.Width + TOP_FIRST_LINE_END_X, startEndY - SHADOW_LINE_BIAS, this.Width - LINE_BIAS, startEndY - SHADOW_LINE_BIAS);
                //left line
                g.DrawLine(linePen, 1, startEndY, 1, this.Height - LINE_BIAS);
                g.DrawLine(lineShadowPen, 0, startEndY, 0, this.Height - LINE_BIAS);
                //bottom line
                g.DrawLine(linePen, 1, this.Height - SHADOW_LINE_BIAS, this.Width - LINE_BIAS, this.Height - SHADOW_LINE_BIAS);
                g.DrawLine(lineShadowPen, 1, this.Height - LINE_BIAS, this.Width - LINE_BIAS, this.Height - LINE_BIAS);
                //right line
                g.DrawLine(linePen, this.Width - LINE_BIAS, startEndY, this.Width - 2, this.Height - LINE_BIAS);
                g.DrawLine(lineShadowPen, this.Width - LINE_BIAS + SHADOW_LINE_BIAS, startEndY, this.Width - LINE_BIAS + SHADOW_LINE_BIAS, this.Height - LINE_BIAS);

            }


        }

        private void computeTextSize(string text)
        {
            
            using (Graphics g = this.CreateGraphics())
            {
                if (!string.IsNullOrWhiteSpace(text))
                {
                    //StringFormat sf = StringFormat.GenericTypographic;
                    //sf.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
                    //this.textSize = g.MeasureString(text.ToUpper(), SkinManager.getFontByType(MaterialSkinManager.fontType.Subtitle2), PointF.Empty, sf);
                    using (NativeTextRenderer NativeText = new NativeTextRenderer(CreateGraphics()))
                    {
                        this.textSize = NativeText.MeasureLogString(text, SkinManager.getLogFontByType((MaterialSkinManager.fontType)_FontType));
                        this.textSize.Width += 1; // necessary to avoid a bug when autosize = true
                    }
                }
                else
                {
                    this.textSize.Width = 0;
                    this.textSize.Height = 0;
                }
            }
        }
    }

    // Font Handling
    public enum GroupBoxFontType
    {
        Subtitle1 = 6,
        Subtitle2 = 7,
        Caption = 12,

    }


}
